﻿using System;
using System.Collections.Generic;

namespace PusherClient
{
    public class Pusher : IPusher
    {
        private readonly string _appKey;
        private readonly string _pusherEndpoint;
        private const string PusherClientName = "dotnet-pusherclient";
        private const int PusherProtocol = 5;
        private const string PusherVersion = "1.12.1";
        private readonly Connection _connection;
        private readonly Dictionary<string, Channel> _channels = new Dictionary<string, Channel>();

        public IConnection Connection
        {
            get { return _connection; }
        }

        public Pusher(string appKey, PusherOptions options = null)
        {
            this._appKey = appKey;
            string port = options != null && options.Encrypted ? "443" : "80";
            string scheme = options != null && options.Encrypted ? "wss" : "ws";
            this._pusherEndpoint = string.Format(
                "{0}://ws.pusherapp.com:{1}/app/{2}?protocol={3}&client={4}&version={5}",
                scheme,
                port,
                this._appKey,
                PusherProtocol,
                PusherClientName,
                PusherVersion);

            this._connection = new Connection(this._pusherEndpoint);
        }

        public IChannel GetChannel(string channelName)
        {
            if (!this._channels.ContainsKey(channelName))
                return null;

            return this._channels[channelName];
        }

        public IChannel Subscribe(string channelName)
        {
            if (!this._channels.ContainsKey(channelName))
                this._channels.Add(channelName, new Channel(channelName, this._connection));

            return this._channels[channelName];
        }

        public void UnSubscribe(string channelName)
        {
            if (!this._channels.ContainsKey(channelName))
                return;
            
            this._channels[channelName].Dispose();
            this._channels.Remove(channelName);
        }

        public void Dispose()
        {
            this.Connection.Dispose();
        }

        ~Pusher()
        {
            this.Dispose();
        }
    }
}
